﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using YanZhiwei.DotNet2.Utilities.Common;

namespace YanZhiwei.DotNet2.Utilities.WinForm
{
    /// <summary>
    /// DataGrid 帮助类
    /// </summary>
    public static class DataGridHelper
    {
        #region DataGridView SetBindingSource
        /// <summary>
        /// DataGridView SetBindingSource
        /// </summary>
        /// <typeparam name="T">IList</typeparam>
        /// <param name="dataGrid">dataGrid</param>
        /// <param name="source">泛型</param>
        public static void SetBindingSource<T>(this DataGridView dataGrid, IList<T> source)
        {
            BindingList<T> _bindinglist = new BindingList<T>(source);
            BindingSource _source = new BindingSource(_bindinglist, null);
            dataGrid.DataSource = _source;
        }
        #endregion
        #region  DataGridView绑定，线程安全
        /// <summary>
        /// DataGridView绑定，线程安全
        /// </summary>
        /// <param name="dataGrid">DataGridView</param>
        /// <param name="dt">DataTable</param>
        public static void BindTF(this DataGridView dataGrid, DataTable dt)
        {
            dataGrid.UIThread(delegate
            {
                dataGrid.DataSource = dt;
                dataGrid.Refresh();
            });
        }
        #endregion
        #region DataGridView绑定。
        /// <summary>
        /// DataGridView绑定。
        /// </summary>
        /// <param name="dataGrid">DataGridView</param>
        /// <param name="dt">DataTable</param>
        public static void Bind(this DataGridView dataGrid, DataTable dt)
        {
            dataGrid.DataSource = dt;
            dataGrid.Refresh();
        }
        #endregion
        #region DataGridView绑定，线程安全
        /// <summary>
        /// DataGridView绑定，线程安全
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="dataGrid">DataGridView对象</param>
        /// <param name="t">数据源</param>
        public static void Bind<T>(this DataGridView dataGrid, IList<T> t)
        {
            BindingList<T> _bindinglist = new BindingList<T>(t);
            BindingSource _source = new BindingSource(_bindinglist, null);
            dataGrid.DataSource = _source;
        }
        /// <summary>
        /// DataGridView绑定，线程安全
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="dataGrid">DataGridView</param>
        /// <param name="t">集合</param>
        public static void BindTF<T>(this DataGridView dataGrid, IList<T> t)
        {
            dataGrid.UIThread(dg =>
            {
                BindingList<T> _bindinglist = new BindingList<T>(t);
                BindingSource _source = new BindingSource(_bindinglist, null);
                dg.DataSource = _source;
            });

        }
        #endregion
        #region 根据行列获取值
        /// <summary>
        /// 根据行列获取值
        /// </summary>
        /// <param name="dataGrid">DataGridView对象</param>
        /// <param name="rowIndex">行数</param>
        /// <param name="columnIndex">列数</param>
        /// <returns>获取值</returns>
        public static object GetCellValue(this DataGridView dataGrid, int rowIndex, int columnIndex)
        {
            object _objCellValue = null;
            _objCellValue = dataGrid.Rows[rowIndex].Cells[columnIndex].Value;
            return _objCellValue;
        }
        #endregion
        #region 根据行列获取值『线程安全』
        /// <summary>
        /// 根据行列获取值『线程安全』
        /// </summary>
        /// <param name="dataGrid">DataGridView对象</param>
        /// <param name="rowIndex">行数</param>
        /// <param name="columnIndex">列数</param>
        /// <returns>获取值</returns>
        public static object GetCellValueTF(this DataGridView dataGrid, int rowIndex, int columnIndex)
        {
            object _objCellValue = null;
            dataGrid.UIThread(delegate
            {
                _objCellValue = dataGrid.Rows[rowIndex].Cells[columnIndex].Value;
            });
            return _objCellValue;
        }
        #endregion
        #region 根据行列设置值『线程安全』
        /// <summary>
        /// 根据行列设置值『线程安全』
        /// </summary>
        /// <param name="dataGrid">DataGridView对象</param>
        /// <param name="rowIndex">行数</param>
        /// <param name="columnIndex">列数</param>
        /// <param name="cellValue">设置的数值</param>
        public static void SetCellValueTF(this DataGridView dataGrid, int rowIndex, int columnIndex, object cellValue)
        {
            dataGrid.UIThread(delegate
            {
                dataGrid.Rows[rowIndex].Cells[columnIndex].Value = cellValue;
            });
        }
        #endregion
        #region 根据行列设置值
        /// <summary>
        /// 根据行列设置值
        /// </summary>
        /// <param name="dataGrid">DataGridView对象</param>
        /// <param name="rowIndex">行数</param>
        /// <param name="columnIndex">列数</param>
        /// <param name="cellValue">设置的数值</param>
        public static void SetCellValue(this DataGridView dataGrid, int rowIndex, int columnIndex, object cellValue)
        {
            dataGrid.Rows[rowIndex].Cells[columnIndex].Value = cellValue;
        }
        #endregion
        #region 根据行数列名获取数值
        /// <summary>
        /// 根据行数列名获取数值
        /// </summary>
        /// <param name="dataGrid">DataGridView对象</param>
        /// <param name="rowIndex">行数</param>
        /// <param name="columnName">列名称</param>
        /// <returns></returns>
        public static object GetCellValueTF(this DataGridView dataGrid, int rowIndex, string columnName)
        {
            object _objCellValue = null;
            dataGrid.UIThread((MethodInvoker)delegate
            {
                _objCellValue = dataGrid.Rows[rowIndex].Cells[columnName].Value;
            });
            return _objCellValue;
        }
        #endregion
        #region  获取列的值
        /// <summary>
        /// 获取列的值
        /// </summary>
        /// <param name="dataGrid">DataGridView</param>
        /// <param name="rowIndex">行索引</param>
        /// <param name="columnName">列名称</param>
        /// <returns>列值</returns>
        public static object GetCellValue(this DataGridView dataGrid, int rowIndex, string columnName)
        {
            return dataGrid.Rows[rowIndex].Cells[columnName].Value;
        }
        #endregion 
        #region cell格式化
        /// <summary>
        /// cell格式化
        /// </summary>
        /// <param name="gridview">DataGridView</param>
        /// <param name="e">DataGridViewCellFormattingEventArgs</param>
        /// <param name="cellName">列名称</param>
        /// <param name="cellValue">列值</param>
        public static void CustomFormatting(this DataGridView gridview, DataGridViewCellFormattingEventArgs e, string cellName, object cellValue)
        {
            if (e.RowIndex < 0) return;
            DataGridViewCell _cell = gridview.Rows[e.RowIndex].Cells[e.ColumnIndex];
            string _cellName = gridview.Columns[e.ColumnIndex].Name;
            if (_cellName.Equals(cellName))
                e.Value = cellValue;
        }
        /// <summary>
        /// cell格式化
        /// </summary>
        /// <param name="gridview">DataGridView</param>
        /// <param name="e">DataGridViewCellFormattingEventArgs</param>
        /// <param name="cellName">列名称</param>
        /// <param name="cellFormatRule">委托</param>
        public static void CustomFormatting(this DataGridView gridview, DataGridViewCellFormattingEventArgs e, string cellName, object cellValue, Predicate<object> cellFormatRule)
        {
            if (e.RowIndex < 0) return;
            if (cellFormatRule == null) return;
            DataGridViewCell _cell = gridview.Rows[e.RowIndex].Cells[e.ColumnIndex];
            string _cellName = gridview.Columns[e.ColumnIndex].Name;
            if (_cellName.Equals(cellName))
            {
                if (cellFormatRule(e.Value))
                    e.Value = cellValue;
            }
        }
        /// <summary>
        /// cell格式化
        /// </summary>
        /// <param name="gridview">DataGridView</param>
        /// <param name="e">DataGridViewCellFormattingEventArgs</param>
        /// <param name="cellName">列名称</param>
        /// <param name="cellFormatRule">委托</param>
        [Obsolete]
        public static void CustomFormatting(this DataGridView gridview, DataGridViewCellFormattingEventArgs e, string cellName, Action<object> cellFormatRule)
        {
            if (e.RowIndex < 0) return;
            if (cellFormatRule == null) return;
            DataGridViewCell _cell = gridview.Rows[e.RowIndex].Cells[e.ColumnIndex];
            string _cellName = gridview.Columns[e.ColumnIndex].Name;
            if (_cellName.Equals(cellName))
                cellFormatRule(e.Value);
        }
        #endregion
        #region 设置单元格数值
        /// <summary>
        /// 设置单元格数值。线程安全
        /// </summary>
        /// <param name="dataGrid">DataGridView</param>
        /// <param name="rowIndex">行</param>
        /// <param name="columnName">列名称</param>
        /// <param name="cellValue">单元格数值</param>
        public static void SetCellValueTF(this DataGridView dataGrid, int rowIndex, string columnName, object cellValue)
        {
            dataGrid.UIThread((MethodInvoker)delegate
            {
                dataGrid.Rows[rowIndex].Cells[columnName].Value = cellValue;
            });
        }

        /// <summary>
        /// 设置单元格数值
        /// </summary>
        /// <param name="dataGrid">DataGridView</param>
        /// <param name="rowIndex">行</param>
        /// <param name="columnName">列名称</param>
        /// <param name="cellValue">单元格数值</param>
        public static void SetCellValue(this DataGridView dataGrid, int rowIndex, string columnName, object cellValue)
        {
            dataGrid.Rows[rowIndex].Cells[columnName].Value = cellValue;
        }
        #endregion
        #region 数据筛选
        /// <summary>
        /// 数据筛选【线程安全】
        /// </summary>
        /// <param name="dataGrid">DataGridView</param>
        /// <param name="columnName">筛选列名</param>
        /// <param name="value">筛选值</param>
        public static void FilterTF(this DataGridView dataGrid, string columnName, object value)
        {
            dataGrid.UIThread(delegate
            {
                (dataGrid.DataSource as DataTable).DefaultView.RowFilter = string.Format("{0} = '{1}'", columnName, value);
            });
        }
        /// <summary>
        /// 数据筛选
        /// </summary>
        /// <param name="dataGrid">DataGridView</param>
        /// <param name="columnName">筛选列名</param>
        /// <param name="value">筛选值</param>
        public static void Filter(this DataGridView dataGrid, string columnName, object value)
        {
            (dataGrid.DataSource as DataTable).DefaultView.RowFilter = string.Format("{0} = '{1}'", columnName, value);
        }
        #endregion
        #region 根据筛选条件，返回所在行数
        /// <summary>
        /// 根据筛选条件，返回所在行数
        /// </summary>
        /// <param name="dataGrid">DataGridView</param>
        /// <param name="columnName">所筛选的列名称</param>
        /// <param name="value">筛选数值</param>
        /// <returns>筛选成功：所在行数；若未找到则返回-1；</returns>
        public static int Filter(this DataGridView dataGrid, string columnName, string value)
        {
            int _rowsIndex = -1;
            foreach (DataGridViewRow row in dataGrid.Rows)
            {
                if (row.Cells[columnName].Value.ToString().Equals(value))
                {
                    _rowsIndex = row.Index;
                    break;
                }
            }
            return _rowsIndex;
        }
        #endregion
        #region 遍历行
        /// <summary>
        /// 遍历行
        /// </summary>
        /// <param name="dataGrid">DataGridView</param>
        /// <param name="loopRowsRule">委托</param>
        public static void LoopRows(this DataGridView dataGrid, Action<string, object> loopRowsRule)
        {
            foreach (DataGridViewRow row in dataGrid.Rows)
            {
                for (int i = 0; i < dataGrid.Columns.Count; i++)
                {
                    string _colName = dataGrid.Columns[i].Name;
                    object _cellValue = row.Cells[_colName].Value;
                    loopRowsRule(_colName, _cellValue);
                }
            }
        }
        /// <summary>
        /// 遍历行
        /// </summary>
        /// <param name="dataGrid">DataGridView</param>
        /// <param name="LoopRowsHanlder">委托</param>
        public static void LoopRows(this DataGridView dataGrid, Action<DataGridViewRow> LoopRowsHanlder)
        {
            foreach (DataGridViewRow row in dataGrid.Rows)
            {
                LoopRowsHanlder(row);
            }
        }
        #endregion
        #region 根据实体类类创建列名称【线程安全】
        /// <summary>
        /// 根据实体类类创建列名称【线程安全】
        /// </summary>
        /// <typeparam name="T">实体类类型</typeparam>
        /// <param name="dataGrid">DataGridView</param>
        /// <param name="t">实体类</param>
        public static void InsertColumnsTF<T>(this DataGridView dataGrid, T t) where T : class
        {
            IDictionary<string, string> _columns = ReflectHelper.GetDisplayName<T>();
            if (_columns == null || _columns.Count <= 0) return;
            foreach (KeyValuePair<string, string> entry in _columns)
            {
                dataGrid.UIThread(delegate
                {
                    if (!dataGrid.Columns.Contains(entry.Key))
                    {
                        DataGridViewTextBoxColumn _column = new DataGridViewTextBoxColumn();
                        _column.Name = entry.Key;
                        _column.HeaderText = entry.Value;
                        dataGrid.Columns.Add(_column);
                    }
                });
            }
        }
        #endregion
        #region 根据实体类类创建列名称并填充数据
        /// <summary>
        /// 根据实体类类创建列名称并填充数据
        /// </summary>
        /// <typeparam name="T">实体类类型</typeparam>
        /// <param name="dataGrid">DataGridView</param>
        /// <param name="t">实体类</param>
        /// <param name="keyColumn">匹配段列</param>
        /// <param name="keyValue">匹配的数值</param>
        public static void InsertColumnsValueTF<T>(this DataGridView dataGrid, T t, string keyColumn, string keyValue) where T : class
        {
            IDictionary<string, string> _columns = ReflectHelper.GetDisplayName<T>();
            if (_columns == null || _columns.Count <= 0) return;
            foreach (KeyValuePair<string, string> entry in _columns)
            {
                dataGrid.UIThread(delegate
                {
                    if (!dataGrid.Columns.Contains(entry.Key))
                    {
                        DataGridViewTextBoxColumn _column = new DataGridViewTextBoxColumn();
                        _column.Name = entry.Key;
                        _column.HeaderText = entry.Value;
                        // _column.SortMode = DataGridViewColumnSortMode.Programmatic;
                        //_column.DataPropertyName = entry.Key;
                        //_column.SortMode = DataGridViewColumnSortMode.Programmatic;
                        //_column.HeaderCell.SortGlyphDirection = SortOrder.None;
                        dataGrid.Columns.Add(_column);
                    }
                    if (!dataGrid.Columns[entry.Key].Visible)
                    {
                        dataGrid.Columns[entry.Key].Visible = true;
                    }
                    object _cellValue = typeof(T).InvokeMember(entry.Key, BindingFlags.GetProperty, null, t, null);
                    int _rowIndex = Filter(dataGrid, keyColumn, keyValue);
                    if (_rowIndex != -1)
                        dataGrid.Rows[_rowIndex].Cells[entry.Key].Value = _cellValue;
                });
            }
        }
        #endregion
        #region 绘制行号，在RowPostPaint事件
        /// <summary>
        /// 绘制行号，在RowPostPaint事件
        /// </summary>
        /// <param name="girdview">DataGridView</param>
        /// <param name="e">DataGridViewRowPostPaintEventArgs</param>
        public static void DrawRowIndex(this DataGridView girdview, DataGridViewRowPostPaintEventArgs e)
        {
            Rectangle _rectangle = new Rectangle(e.RowBounds.Location.X, e.RowBounds.Location.Y, girdview.RowHeadersWidth, e.RowBounds.Height);
            TextRenderer.DrawText(e.Graphics, (e.RowIndex + 1).ToString(),
                girdview.RowHeadersDefaultCellStyle.Font,
                _rectangle,
                girdview.RowHeadersDefaultCellStyle.ForeColor,
                TextFormatFlags.VerticalCenter | TextFormatFlags.Right);
        }
        #endregion
        #region 根据cell内容调整其宽度
        /// <summary>
        /// 根据cell内容调整其宽度
        /// </summary>
        /// <param name="girdview">DataGridView</param>
        public static void AutoCellWidth(this DataGridView girdview)
        {
            girdview.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
            girdview.AutoResizeColumns();
            girdview.AllowUserToResizeColumns = true;
        }
        #endregion
        #region 设置cell的toolTip
        /// <summary>
        /// 设置cell的toolTip
        ///<para>eg:</para> 
        ///<para>datagrid.CellToolTip((DataGridViewCell cell) =></para> 
        ///<para>{</para> 
        ///<para>    cell.ToolTipText = CSharpToolV2.WrapText(cell.Value.ToString(), 40);</para> 
        ///<para>});</para> 
        /// </summary>
        /// <param name="girdview">DataGridView</param>
        /// <param name="cellTooltipRule">委托</param>
        [Obsolete]
        public static void CellToolTip(this DataGridView girdview, Action<DataGridViewCell> cellTooltipRule)
        {
            foreach (DataGridViewRow row in girdview.Rows)
            {
                foreach (DataGridViewCell cell in row.Cells)
                {
                    cellTooltipRule(cell);
                }
            }
        }
        #endregion
    }
}
